/*
 * Project: Daycare Web Application
 * Package: com.made2ordersoftware.daycare.domain
 * File:    TimeWatchedEntity.java
 * Created: Dec 20, 2010
 */
/**
 * Copyright (c) 2010 Made 2 Order Software, LLC
 *
 * All rights reserved. No part of this software may be reproduced, stored in a retrieval system, or
 * transmitted in any form or by any means, without the prior written permission of Made 2 Order Software.
 *
 * You may not distribute the URL or redistribute the files to third parties. You may transfer the files onto
 * a single storage device so long as you can prove ownership of the software. You may not reverse engineer,
 * decompile, or disassemble the software or media files. You may not modify or translate the software or
 * media, or distribute copies of the software or media without the written consent of Made 2 Order Software,
 * LLC.
 */
package com.made2ordersoftware.daycare.domain;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Comparator;
import java.util.Objects;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.made2ordersoftware.util.StringUtility;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * Entity class representing the date and times a child is signed into the day care.
 *
 * @author David Canning <dcannin@gmail.com>
 * @version 1.0.0
 */
@Entity
@Table(name = "time_watched")
@NamedQueries({
    @NamedQuery(name = "TimeWatched.findSignInRecord", query = "SELECT t FROM TimeWatchedEntity t WHERE t.child.id = :childId and t.dateTimeOut IS NULL"),
    @NamedQuery(name = "TimeWatched.findChildrenSignedIn", query = "SELECT t.child.id FROM TimeWatchedEntity t WHERE t.dateTimeOut IS NULL"),
    @NamedQuery(name = "TimeWatched.findByDates", query = "SELECT t FROM TimeWatchedEntity t WHERE t.dateTimeIn >= :startDate and t.dateTimeOut <= :stopDate ORDER BY t.dateTimeIn, t.parent.id, t.child.id"),
    @NamedQuery(name = "TimeWatched.findByAge", query = "SELECT t FROM TimeWatchedEntity t WHERE t.dateTimeIn >= :startDate and t.dateTimeOut <= :stopDate ORDER BY t.age, t.dateTimeIn, t.parent.id, t.child.id"),
    @NamedQuery(name = "TimeWatched.findByParent", query = "SELECT t FROM TimeWatchedEntity t WHERE t.dateTimeIn >= :startDate and t.dateTimeOut <= :stopDate and t.parent.id = :parentId ORDER BY t.age, t.dateTimeIn, t.child.id"),
    @NamedQuery(name = "TimeWatched.findByChild", query = "SELECT t FROM TimeWatchedEntity t WHERE t.dateTimeIn >= :startDate and t.dateTimeOut <= :stopDate and t.child.id = :childId ORDER BY t.age, t.dateTimeIn, t.parent.id")})
@XmlRootElement
public class TimeWatchedEntity implements Serializable {

    private static final Logger LOG = LoggerFactory.getLogger(TimeWatchedEntity.class);
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    private Long id;
    @Basic(optional = false)
    @Column(name = "date_in")
    private Timestamp dateTimeIn;
    @Column(name = "date_out")
    private Timestamp dateTimeOut;
    @Basic(optional = false)
    private float fee;
    @Basic(optional = false)
    private int age;
    @JoinColumn(name = "child_id", referencedColumnName = "id", nullable = false, updatable = false)
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    private ChildEntity child;
    @JoinColumn(name = "parent_id", referencedColumnName = "id", nullable = false, updatable = false)
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    private ParentEntity parent;

    /**
     * Creates an instance of <code>TimeWatchedEntity</code>.
     */
    public TimeWatchedEntity() {
    }

    /**
     * Creates an instance of <code>TimeWatchedEntity</code>.
     *
     * @param parent     The parent of the child being signed into the day care system.
     * @param child      The child being signed into the day care system.
     * @param dateTimeIn Date and time child was signed into the day care.
     * @param fee        Fee at which to charge the child for this stay.
     * @param age        Age of child at time of sign in.
     */
    public TimeWatchedEntity(ParentEntity parent, ChildEntity child, Timestamp dateTimeIn, float fee, int age) {
        this.parent = parent;
        this.child = child;
        this.dateTimeIn = dateTimeIn;
        this.fee = fee;
        this.age = age;
    }

    /**
     * Returns the id of the TimeWacthedEntity.
     *
     * @return ID
     */
    public Long getId() {
        return id;
    }

    /**
     * Sets the id of the TimeWacthedEntity.
     *
     * @param id
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * Returns the fee of the TimeWatchedEntity.
     *
     * @return the fee of current sign in record
     */
    public float getFee() {
        return fee;
    }

    /**
     * Sets the fee of the TimeWatchedEntity.
     *
     * @param fee
     */
    public void setFee(float fee) {
        this.fee = fee;
    }

    /**
     * Returns the age of the TimeWatchedEntity.
     *
     * @return the age of current sign in record
     */
    public int getAge() {
        return age;
    }

    /**
     * Sets the age of the TimeWatchedEntity.
     *
     * @param age the age to set
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * Returns the Child associated with this TimeWatchedEntity.
     *
     * @return the child of current sign in record
     */
    public ChildEntity getChild() {
        return child;
    }

    /**
     * Sets the Child associated with this TimeWatchedEntity.
     *
     * @param child
     */
    public void setChild(ChildEntity child) {
        this.child = child;
    }

    /**
     * Returns the Parent associated with this TimeWatchedEntity.
     *
     * @return the parent of current sign in record
     */
    public ParentEntity getParent() {
        return parent;
    }

    /**
     * Sets the Parent associated with this TimeWatchedEntity.
     *
     * @param parent
     */
    public void setParent(ParentEntity parent) {
        this.parent = parent;
    }

    /**
     * @return the dateTimeIn of current sign in record
     */
    public Timestamp getDateTimeIn() {
        return dateTimeIn;
    }

    /**
     * @param dateTimeIn the dateTimeIn to set
     */
    public void setDateTimeIn(Timestamp dateTimeIn) {
        this.dateTimeIn = dateTimeIn;
    }

    /**
     * @return the dateTimeOut of current sign in record
     */
    public Timestamp getDateTimeOut() {
        return dateTimeOut;
    }

    /**
     * @param dateTimeOut the dateTimeOut to set
     */
    public void setDateTimeOut(Timestamp dateTimeOut) {
        this.dateTimeOut = dateTimeOut;
    }

    @Override
    public int hashCode() {
        int hash = 2;
        hash = 15 * Objects.hashCode(this.id);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof TimeWatchedEntity)) {
            return false;
        }
        TimeWatchedEntity other = (TimeWatchedEntity) object;
        return (Objects.equals(this.child, other.getChild()) && Objects.equals(this.dateTimeIn, other
                .getDateTimeIn()));
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("\nTimeWatchedEntity{ id=").append(
                StringUtility.ifNotNullToString(getId()));
        sb.append("\n\tParent ID=").append(this.parent.getId());
        sb.append("\n\tChild ID=").append(this.child.getId());
        sb.append("\n\tDate in=").append(this.dateTimeIn);
        sb.append("\n\tDate out=").append(this.dateTimeOut);
        sb.append("\n\tAge=").append(this.age);
        sb.append("\n\tFee=").append(this.fee);
        sb.append("}");
        return sb.toString();
    }

    /**
     * Inner class used to compare the TimeWatchedEntity object by age. This is used for multi-column compare
     * operations.
     */
    public class AgeComparator implements Comparator<TimeWatchedEntity> {

        @Override
        public int compare(TimeWatchedEntity o1, TimeWatchedEntity o2) {
            //LOG.info("HI 2");
            return o1.getAge() - o2.getAge();
        }
    }

    /**
     * Inner class used to compare the TimeWatchedEntity object by Child ID. This is used for multi-column
     * compare operations.
     */
    public class ChildIdComparator implements Comparator<TimeWatchedEntity> {

        @Override
        public int compare(TimeWatchedEntity o1, TimeWatchedEntity o2) {
            return (int) (o1.getChild().getId() - o2.getChild().getId());
        }
    }

    /**
     * Inner class used to compare the TimeWatchedEntity object by date. This is used for multi-column compare
     * operations.
     */
    public class DateComparator implements Comparator<TimeWatchedEntity> {

        @Override
        public int compare(TimeWatchedEntity o1, TimeWatchedEntity o2) {
            return o1.getDateTimeIn().compareTo(o2.getDateTimeIn());
        }
    }

}
